package com.felix.aspect;

import com.felix.annotation.MyLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * LogAspect
 *
 * @author xjh
 * @version 1.0
 * @date 2019-05-21
 */
@Component
@Aspect
public class LogAspect {

    @Pointcut("@annotation(com.felix.annotation.MyLog)")
    public void pointCut() {
    }

    @Around(value = "pointCut()")
    public Object handleLog(ProceedingJoinPoint joinPoint) throws Throwable {
        Map<String, Object> params = getNameAndValue(joinPoint);
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            System.out.println("name: " + entry.getKey() + " value: " + entry.getValue());
        }
        Object object = joinPoint.proceed();
        return object;
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private static MyLog getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(MyLog.class);
        }
        return null;
    }

    /**
     * 获取参数Map集合
     *
     * @param joinPoint
     * @return
     */
    Map<String, Object> getNameAndValue(ProceedingJoinPoint joinPoint) {
        Map<String, Object> param = new HashMap<>();
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        for (int i = 0; i < paramNames.length; i++) {
            param.put(paramNames[i], paramValues[i]);
        }
        return param;
    }
}
